package com.tanhua.houtai.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tanhua.common.mapper.UserInfoMapper;
import com.tanhua.common.mapper.UserMapper;
import com.tanhua.common.pojo.User;
import com.tanhua.common.pojo.UserInfo;
import com.tanhua.houtai.mapper.AnalysisByDayMapper;
import com.tanhua.houtai.pojo.AnalysisByDay;
import com.tanhua.houtai.utils.AreaUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class HomePageService {

    @Autowired
    private AnalysisByDayMapper analysisByDayMapper;

    @Autowired
    private AdminService adminService;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserInfoMapper userInfoMapper;

    private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");

    /**
     * 新增 活跃 次日留存率
     *
     * @param token
     * @param start
     * @param end
     * @param type
     * @return
     */
    public Map<String, Object> users(String token, String start, String end, String type) {
        //校验token
        Boolean flag = this.adminService.queryUserByToken(token);
        if (flag) {

            //转换时间格式
            long startL = Long.parseLong(start);
            Date date = new Date(startL);
            start = simpleDateFormat.format(date);

            long endL = Long.parseLong(end);
            Date date1 = new Date(endL);
            end = simpleDateFormat.format(date1);

            //查询结果  今年的结果
            QueryWrapper<AnalysisByDay> query = new QueryWrapper<>();
            query.between("record_date", start, end).orderByAsc("record_date");
            List<AnalysisByDay> thisLists = this.analysisByDayMapper.selectList(query);

            //获取去年要查的时间
            Calendar calendar = new GregorianCalendar();
            calendar.setTime(date);
            calendar.add(Calendar.YEAR, -1);
            String lastStart = simpleDateFormat.format(calendar.getTime());

            calendar.setTime(date1);
            calendar.add(Calendar.YEAR, -1);
            String lastEnd = simpleDateFormat.format(calendar.getTime());
            //查询结果  去年的结果
            QueryWrapper<AnalysisByDay> query1 = new QueryWrapper<>();
            query.between("record_date", lastStart, lastEnd).orderByAsc("record_date");
            List<AnalysisByDay> lastLists = this.analysisByDayMapper.selectList(query1);

            Map<String, Object> mapAll = new HashMap<>();

            //判断是否有结果
            if (CollUtil.isNotEmpty(thisLists)) {
                List<Object> fill = fill(thisLists, type);
                mapAll.put("thisYear", fill);
            } else {
                mapAll.put("thisYear", null);
            }

            if (CollUtil.isNotEmpty(lastLists)) {
                List<Object> fill = fill(lastLists, type);
                mapAll.put("lastYear", fill);
            } else {
                mapAll.put("lastYear", null);
            }

            return mapAll;

        }
        //token 无效
        return null;
    }

    /**
     * 填充数据
     *
     * @param thisLists
     * @param type
     * @return
     */
    public List<Object> fill(List<AnalysisByDay> thisLists, String type) {

        List<Object> objectList = new ArrayList<>();
        //判断是要什么结果  101：新增  102：活跃用户    103：次日留存率
        if ("101".equals(type)) {
            for (AnalysisByDay list : thisLists) {
                Map<String, Object> map = new HashMap<>();
                Date recordDate = list.getRecordDate();
                String recode = simpleDateFormat.format(recordDate);
                Integer numRegistered = list.getNumRegistered();
                map.put("title", recode);
                map.put("amount", numRegistered);
                objectList.add(map);
            }
            return objectList;
        }
        if ("102".equals(type)) {
            for (AnalysisByDay list : thisLists) {
                Map<String, Object> map = new HashMap<>();
                Date recordDate = list.getRecordDate();
                String recode = simpleDateFormat.format(recordDate);
                Integer numActive = list.getNumActive();
                map.put("title", recode);
                map.put("amount", numActive);
                objectList.add(map);
            }
            return objectList;
        }
        if ("103".equals(type)) {
            for (AnalysisByDay list : thisLists) {
                Map<String, Object> map = new HashMap<>();
                Date recordDate = list.getRecordDate();
                String recode = simpleDateFormat.format(recordDate);
                Integer numRetention1d = list.getNumRetention1d();
                Integer numRegistered = list.getNumRegistered();
                Integer i = 0;
                if (numRegistered == 0) {
                    i = numRetention1d;
                }
                if (numRetention1d == 0) {
                    i = -numRegistered;
                }
                if (numRegistered != 0 && numRetention1d != 0) {
                    i = (numRetention1d / numRegistered) * 100;
                }
                map.put("title", recode);
                map.put("amount", i);
                objectList.add(map);
            }
            return objectList;
        }
        //输入数据错误
        return null;
    }

    /**
     * 首页展示数据  用户累计用户  活跃用户
     *
     * @param token
     * @return
     */
    public Map<String, Object> summary(String token) {

        Boolean flag = adminService.queryUserByToken(token);
        if (flag) {
            Map<String, Object> map = new HashMap<>();
            //查询累计用户
            Integer count = queryCount();
            map.put("cumulativeUsers", count);

            //查询七日活跃用户
            Integer sevDayLive = sevDayLive();
            map.put("activePassWeek", sevDayLive);

            //查询三十日活跃用户
            Integer sanshiDayLive = sanshiDayLive();
            map.put("activePassMonth", sanshiDayLive);

            //获取当日数据
            AnalysisByDay todayData = this.todayData();
            //如果数据为空  需要的数据设置为0
            if (null == todayData) {
                todayData = new AnalysisByDay();
                todayData.setNumRegistered(0);
                todayData.setNumLogin(0);
                todayData.setNumActive(0);
            }

            //当日新增用户
            map.put("newUsersToday", todayData.getNumRegistered());
            //当日登录次数
            map.put("loginTimesToday", todayData.getNumLogin());
            //当日活跃用户
            map.put("activeUsersToday", todayData.getNumActive());

            //获取昨日数据
            AnalysisByDay yestDayData = this.ysedayData();
            if (null == yestDayData) {
                yestDayData = new AnalysisByDay();
                yestDayData.setNumRegistered(0);
                yestDayData.setNumLogin(0);
                yestDayData.setNumActive(0);

            }

            Integer newUsersTodayRate = 0;
            if (yestDayData.getNumRegistered() == 0) {
                newUsersTodayRate = todayData.getNumRegistered();
            }

            if (todayData.getNumRegistered() == 0) {
                newUsersTodayRate = -yestDayData.getNumRegistered();
            }

            if (todayData.getNumRegistered() != 0 && yestDayData.getNumRegistered() != 0) {
                //获取新增用户率
                newUsersTodayRate = (todayData.getNumRegistered() - yestDayData.getNumRegistered()) / (ysedayData().getNumRegistered());
            }

            //今日新增用户涨跌率
            map.put("newUsersTodayRate", newUsersTodayRate * 100);

            Integer loginTimesTodayRate = 0;
            if (yestDayData.getNumLogin() == 0) {
                loginTimesTodayRate = todayData.getNumLogin();
            }

            if (todayData.getNumLogin() == 0) {
                loginTimesTodayRate = -yestDayData.getNumLogin();
            }

            if (todayData.getNumLogin() != 0 && yestDayData.getNumLogin() != 0) {
                //获取登录次数率
                loginTimesTodayRate = (todayData.getNumLogin() - yestDayData.getNumLogin()) / (yestDayData.getNumLogin());
            }

            //今日登录次数涨跌率
            map.put("loginTimesTodayRate", loginTimesTodayRate * 100);

            Integer activeUsersTodayRate = 0;
            if (yestDayData.getNumActive() == 0) {
                activeUsersTodayRate = todayData.getNumActive();
            }

            if (todayData.getNumActive() == 0) {
                activeUsersTodayRate = -yestDayData.getNumActive();
            }

            if (todayData.getNumActive() != 0 && yestDayData.getNumActive() != 0) {
                //获取活跃用户率
                activeUsersTodayRate = (todayData.getNumActive() - yestDayData.getNumActive()) / (yestDayData.getNumActive());
            }

            //今日活跃用户涨跌率
            map.put("activeUsersTodayRate", activeUsersTodayRate * 100);


            //昨日活跃用户
            map.put("activeUsersYesterday", yestDayData.getNumActive());

            //获取前天数据
            AnalysisByDay yestToYestDayData = yestToYestDayData();

            if (null == yestToYestDayData) {
                yestToYestDayData = new AnalysisByDay();
                yestToYestDayData.setNumActive(0);
            }

            Integer activeUsersYesterdayRate = 0;
            if (yestToYestDayData.getNumActive() == 0) {
                activeUsersYesterdayRate = todayData.getNumActive();
            }

            if (yestDayData.getNumActive() == 0) {
                activeUsersYesterdayRate = -yestToYestDayData.getNumActive();
            }

            if (yestDayData.getNumActive() != 0 && yestToYestDayData.getNumActive() != 0) {
                //获取昨日用户活跃率
                activeUsersYesterdayRate = (yestDayData.getNumActive() - yestToYestDayData.getNumActive()) / (yestToYestDayData.getNumActive());
            }

            //昨日活跃用户涨跌率
            map.put("activeUsersYesterdayRate", activeUsersYesterdayRate * 100);
            return map;

        }
        //token 无效
        return null;
    }


    /**
     * 查询昨日数据
     *
     * @return
     */

    public AnalysisByDay ysedayData() {
        QueryWrapper<AnalysisByDay> querycount = new QueryWrapper<>();
        //获取昨天的数据
        DateTime yesterday = DateUtil.yesterday();
        yesterday = DateUtil.parse(yesterday.toString(), "yyyy-MM-dd");
        querycount.eq("record_date", yesterday);
        AnalysisByDay analysisByDayYestDay = this.analysisByDayMapper.selectOne(querycount);
        if (ObjectUtil.isNotEmpty(analysisByDayYestDay)) {
            return analysisByDayYestDay;
        }
        //没有查询到数据
        return null;


    }

    /**
     * 获取前日数据
     *
     * @return
     */
    public AnalysisByDay yestToYestDayData() {

        QueryWrapper<AnalysisByDay> querycount = new QueryWrapper<>();

        //获取前天时间
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(new Date());
        calendar.add(Calendar.DATE, -2);
        String format = simpleDateFormat.format(calendar.getTime());
        querycount.eq("record_date", format);

        //获取前天数据
        AnalysisByDay analysisByDayToday = this.analysisByDayMapper.selectOne(querycount);
        if (ObjectUtil.isNotEmpty(analysisByDayToday)) {
            return analysisByDayToday;
        }
        //没有查询到数据
        return null;

    }

    /**
     * 获取今日数据
     *
     * @return
     */
    public AnalysisByDay todayData() {

        QueryWrapper<AnalysisByDay> querycount = new QueryWrapper<>();

        //获取今天的数据
        String today = DateUtil.today();
        querycount.eq("record_date", today);
        AnalysisByDay analysisByDayToday = this.analysisByDayMapper.selectOne(querycount);
        if (ObjectUtil.isNotEmpty(analysisByDayToday)) {
            return analysisByDayToday;
        }
        //没有查询到数据
        return null;

    }

    /**
     * 获取三十日的活跃用户
     *
     * @return
     */
    public Integer sanshiDayLive() {

        QueryWrapper<User> querycount = new QueryWrapper<>();

        //获取上个月今天
        DateTime dateTime = DateUtil.lastMonth();
        querycount.gt("updated", dateTime);
        Integer integer = this.userMapper.selectCount(querycount);
        if (integer != 0) {
            return integer;
        }
        //没有查询到数据
        return 0;
    }

    /**
     * 获取七天的活跃用户
     *
     * @return
     */
    public Integer sevDayLive() {
        QueryWrapper<User> querycount = new QueryWrapper<>();

        //获取上周今天
        DateTime dateTime = DateUtil.lastWeek();
        querycount.gt("updated", dateTime);
        Integer integer = this.userMapper.selectCount(querycount);
        if (integer != 0) {
            return integer;
        }
        //没有查询到数据
        return 0;
    }

    /**
     * 查询累计用户
     *
     * @return
     */
    private Integer queryCount() {
       /* QueryWrapper<AnalysisByDay> query = new QueryWrapper<>();
        query.select("sum(num_registered) num_registered");
        List<Map<String, Object>> maps = this.analysisByDayMapper.selectMaps(query);
        System.out.println(maps);
        if (CollUtil.isNotEmpty(maps)) {
            Integer count = Integer.valueOf(maps.get(0).get("numRegistered").toString());
            return count;
        }*/

        QueryWrapper<User> query = new QueryWrapper<>();
        Integer integer = this.userMapper.selectCount(query);
        //没有查询到数据
        return integer;
    }


    /**
     * 首页展示数据  注册用户分布，行业top、年龄、性别、地区
     *
     * @param token
     * @param sd
     * @param ed
     * @return
     */
    public Map<String, Object> distribution(String token, String sd, String ed) {
        //校验token
        Boolean flag = this.adminService.queryUserByToken(token);
        Map<String, Object> map = new HashMap<>();
        if (flag) {
            //token 通过

            //  根据传递过来的时间 查询 数据
           //转换时间格式
           /* long startL = Long.parseLong(sd);
            Date date = new Date(startL);
            DateTime start = DateUtil.beginOfDay(date);


            long endL = Long.parseLong(ed);
            Date date1 = new Date(endL);
            DateTime end = DateUtil.endOfDay(date1);*/

            //查询行业top
            QueryWrapper<UserInfo> query = new QueryWrapper<>();
            query.select("count(id) amount", "industry title")

                    //根据传递过来的时间查询数据
                    //.between("created",start,end)

                    .groupBy("industry")
                    //倒叙排序 获取前10
                    .orderByDesc("amount");
            //限制前10 条数据
            query.last("limit 10");
            List<Map<String, Object>> lists = this.userInfoMapper.selectMaps(query);
            //由于前台显示的数据时正序排序   将集合反转
            Collections.reverse(lists);
            //行业top10 数据
            map.put("industryDistribution", lists);

            //查询年龄分布
            List<Map<String, Object>> list = new ArrayList<>();
            list.add(findAge(18, 25));
            list.add(findAge(26, 35));
            list.add(findAge(36, 50));
            list.add(findAge(51, 60));

            //通过传入时间 查询到的年龄分布
           /* list.add(findAge(18, 25,start,end));
            list.add(findAge(26, 35,start,end));
            list.add(findAge(36, 50,start,end));
            list.add(findAge(51, 60,start,end));*/

           //年龄分布 数据
            map.put("ageDistribution", list);

            //查询性别分布
            QueryWrapper<UserInfo> queryAge = new QueryWrapper<>();
            queryAge.select("count(id) amount", "sex title")

                    //根据传递过来的时间查询数据
                    //.between("created",start,end)

                    .groupBy("sex");
            List<Map<String, Object>> mapList = this.userInfoMapper.selectMaps(queryAge);
            for (Map<String, Object> stringObjectMap : mapList) {
                int title = (int) stringObjectMap.get("title");
                if (title == 1) {
                    stringObjectMap.put("title", "男性用户");
                }
                if (title == 2) {
                    stringObjectMap.put("title", "女性用户");
                }
                if (title == 3) {
                    stringObjectMap.put("title", "未知用户");
                }
            }
            //性别分布  数据
            map.put("genderDistribution", mapList);

            //查询地区分布
            QueryWrapper<UserInfo> queryArea = new QueryWrapper<>();
            queryArea.select("count(id) amount", "city title")

                    .groupBy("city");
            List<Map<String, Object>> listArea = this.userInfoMapper.selectMaps(queryArea);
            for (Map<String, Object> stringObjectMap : listArea) {

                String title = (String) stringObjectMap.get("title");
                String[] split = title.split("-");
                String oldAre = split[0];
                if (oldAre.startsWith("黑龙江") || oldAre.startsWith("内蒙古")) {
                    stringObjectMap.put("title", oldAre.substring(0, 3));
                } else {
                    stringObjectMap.put("title", oldAre.substring(0, 2));
                }

            }

            //拼凑数据
            for (int i = 0; i < listArea.size(); i++) {
                for (int i1 = i + 1; i1 < listArea.size(); i1++) {
                    if (listArea.get(i).get("title").equals(listArea.get(i1).get("title"))) {
                        listArea.get(i).put("title", listArea.get(i).get("title"));
                        int count1 = Integer.valueOf(listArea.get(i).get("amount").toString());
                        int count2 = Integer.valueOf(listArea.get(i1).get("amount").toString());
                        listArea.get(i).put("amount", count1 + count2);
                        listArea.remove(i1);
                    }
                }
            }
            //  地区分布 数据
            map.put("localDistribution", listArea);


            //整理地区合计数据
            Map<String, Object> aresMap = new HashMap<>();
            for (Map<String, Object> objectMap : listArea) {
                String title = (String) objectMap.get("title");
                String ares = AreaUtils.get(title);

                //集合为空 直接放入数据
                if (CollUtil.isEmpty(aresMap)) {
                    aresMap.put(ares, objectMap.get("amount"));
                }

                //判断集合是不是存在该数据
                if (ObjectUtil.isNotEmpty(aresMap.get(ares))) {
                    Integer amount = Integer.valueOf(aresMap.get(ares).toString())
                            + Integer.valueOf(objectMap.get("amount").toString());
                    aresMap.put(ares, amount);
                } else {
                    aresMap.put(ares, objectMap.get("amount"));
                }
            }

            List<Map<String, Object>> aresList = new ArrayList<>();
            Set<Map.Entry<String, Object>> entries = aresMap.entrySet();
            for (Map.Entry<String, Object> entry : entries) {
                Map<String, Object> newMap = new HashMap<>();
                newMap.put("title", entry.getKey());
                newMap.put("amount", entry.getValue());
                aresList.add(newMap);
            }
            // 地区合计  数据
            map.put("localTotal", aresList);

            return map;

        }

        //token不通过
        return null;
    }


    /**
     * 查找年龄段信息
     *
     * @return
     */
    public Map<String, Object> findAge(int start, int end) {
        QueryWrapper<UserInfo> queryAge = new QueryWrapper<>();
        queryAge.between("age", start, end);
        Integer countAge = this.userInfoMapper.selectCount(queryAge);
        Map<String, Object> map = new HashMap<>();
        map.put("title", start + "-" + end + "岁");
        map.put("amount", countAge);
        return map;
    }

    //通过传入时间，查询到的年龄分布
   /* public Map<String, Object> findAge(int start, int end,DateTime creStart , DateTime creEnd) {
        QueryWrapper<UserInfo> queryAge = new QueryWrapper<>();
        queryAge.between("age", start, end)
        .between("created",creStart,creEnd);
        Integer countAge = this.userInfoMapper.selectCount(queryAge);
        Map<String, Object> map = new HashMap<>();
        map.put("title", start + "-" + end + "岁");
        map.put("amount", countAge);
        return map;
    }*/


}
